package com.gupao.rpc.protocol.codec;

import com.gupao.rpc.protocol.constants.ReqType;
import com.gupao.rpc.protocol.constants.RpcConstant;
import com.gupao.rpc.protocol.protocol.Header;
import com.gupao.rpc.protocol.protocol.RpcProtocol;
import com.gupao.rpc.protocol.protocol.RpcRequest;
import com.gupao.rpc.protocol.protocol.RpcResponse;
import com.gupao.rpc.protocol.serializer.IRpcSerializer;
import com.gupao.rpc.protocol.serializer.RpcSerializerManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 解码器
 *
 * @author SuperWein
 */
@Slf4j
public class RpcDecoder extends ByteToMessageDecoder {


    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
        log.info("========begin RpcDecoder==========");
        if (in.readableBytes() < RpcConstant.HEAD_TOTOAL_LEN) {
            return;
        }
        // 标记读取开始索引 ?????
        in.markReaderIndex();
        // 校验魔数
        short magic = in.readShort();
        if (magic != RpcConstant.MAGIC) {
            throw new IllegalArgumentException("Illegal request header 'magic' : " + magic);
        }
        // 读取消息头内容
        byte reqType = in.readByte();
        byte serialType = in.readByte();
        long requestId = in.readLong();
        int contentLength = in.readInt();
        // 消息头内容是否完成
        if (in.readableBytes() < contentLength) {
            // 重置读取开始索引
            in.resetReaderIndex();
            return;
        }
        // 读取消息体内容
        byte[] bodyBytes = new byte[contentLength];
        in.readBytes(bodyBytes);
        // 消息头
        Header header = new Header(magic, reqType, serialType, requestId, contentLength);
        IRpcSerializer serializer = RpcSerializerManager.getSerializer(serialType);
        ReqType rt = ReqType.getReqType(reqType);
        switch (rt) {
            case REQUEST:
                RpcRequest rpcRequest = serializer.deserialize(bodyBytes, RpcRequest.class);
                RpcProtocol<RpcRequest> requestRpcProtocol = new RpcProtocol<>();
                requestRpcProtocol.setHeader(header);
                requestRpcProtocol.setBody(rpcRequest);
                list.add(requestRpcProtocol);
                break;
            case RESPONSE:
                RpcResponse rpcResponse = serializer.deserialize(bodyBytes, RpcResponse.class);
                RpcProtocol<RpcResponse> responseRpcProtocol = new RpcProtocol<>();
                responseRpcProtocol.setHeader(header);
                responseRpcProtocol.setBody(rpcResponse);
                list.add(responseRpcProtocol);
                break;
            case HEARTBEAT:
                // TODO
                break;
            default:
                break;
        }
    }

}
